package vip.liux.backend.application.serviceImpl.product;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import vip.liux.application.dots.PagedResultDto;
import vip.liux.backend.application.service.product.*;
import vip.liux.backend.infrastructure.code.BizCodeGenerator;
import vip.liux.contracts.models.product.Brand;
import vip.liux.contracts.repositories.product.BrandRepository;
import vip.liux.contracts.shared.value.Select;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class BrandServiceImpl implements BrandService {

    private final BrandRepository brandRepository;
    private final BizCodeGenerator codeGenerator;

    public BrandServiceImpl(BrandRepository brandRepository, BizCodeGenerator codeGenerator) {
        this.brandRepository = brandRepository;
        this.codeGenerator = codeGenerator;
    }

    @Override
    public BrandDto createBrand(CreateBrandDto brandDto) {
        Brand brand = AutoMapperProfile.INSTANCE.toEntity(brandDto);
        brand.setBrandNo(codeGenerator.generateBrandNo());
        brand = brandRepository.save(brand);
        return toDto(brand);
    }

    @Override
    public List<BrandDto> getAllBrands() {
        return brandRepository.findAll().stream().map(this::toDto).collect(Collectors.toList());
    }

    @Override
    public BrandDto getBrandById(Long id) {
        Brand brand = brandRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("entry not found"));
        return toDto(brand);
    }

    @Override
    public BrandDto updateBrand(Long id, CreateBrandDto brandDto) {
        Brand brand = brandRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Brand not found"));
        AutoMapperProfile.INSTANCE.partialUpdate(brandDto, brand);
        brand = brandRepository.save(brand);
        return toDto(brand);
    }

    @Override
    public void deleteBrand(Long id) {
        brandRepository.deleteById(id);
    }

    @Override
    public PagedResultDto<BrandDto> getBrands(BrandQueryDto queryDto) {
        Page<Brand> page = brandRepository.findAllByKeyword(PageRequest.of(queryDto.getPage(), queryDto.getMaxResultCount()), queryDto.getSearch());
        return new PagedResultDto<>(page.getContent().stream().map(this::toDto).collect(Collectors.toList()), page.getTotalElements());
    }

    @Override
    public List<Select> getBrandOptions() {
        return brandRepository.findAll().stream().map(AutoMapperProfile.INSTANCE::toSelectOption).collect(Collectors.toList());
    }

    @Override
    public BrandDto findByBrandNo(String brandNo) {
        Brand brand = brandRepository.findByBrandNo(brandNo).orElseThrow(() -> new IllegalArgumentException("entry not found"));
        return toDto(brand);
    }

    private BrandDto toDto(Brand brand) {
        return AutoMapperProfile.INSTANCE.toDto(brand);
    }
}